package com.trtan.hr.config;

import com.trtan.hr.dao.MenuDao;
import com.trtan.hr.pojo.Hr;
import com.trtan.hr.pojo.Menu;
import com.trtan.hr.pojo.Role;
import com.trtan.hr.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;

/**
 * 实现动态配置资源访问权限(菜单访问权限)
 * FilterInvocationSecurityMetadataSource默认实现类是DefaultFilterInvocationSecurityMetadataSource
 * 可以参考DefaultFilterInvocationSecurityMetadataSource来定义自己的FilterInvocationSecurityMetadataSource
 * @author trtan
 */
@Component
public class CustomFilterInvocationSecurityMetadataSource
        implements FilterInvocationSecurityMetadataSource {
    /* 主要用来实现ant风格的url匹配 */
    AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    MenuService menuService;
    /**
     * 确定一个请求需要哪些角色
     * @param o
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        //从FilterInvocation实例中提取请求的url
        String requestUrl = ((FilterInvocation) o).getRequestUrl();
        //从数据库获取所有的资源信息(菜单模式)，也可以改用从缓存中获取
        List<Menu> menus = menuService.getAllMenus();
        //遍历所有的菜单模式
        for (Menu menu : menus) {
            //判断请求url是否匹配菜单模式
            if (antPathMatcher.match(menu.getUrl(), requestUrl) && menu.getRoles().size() > 0) {
                //获取菜单模式所有角色
                List<Role> roles = menu.getRoles();
                String[] roleArr = new String[roles.size()];
                for (int i = 0; i < roleArr.length; i++) {
                    roleArr[i] = roles.get(i).getName();
                }
                //返回所有角色信息
                return SecurityConfig.createList(roleArr);
            }
        }
        //如果请求的url在数据库菜单表中不存在相应的模式，则登陆后即可访问，给与login角色
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    /**
     * 返回所有定义好的角色资源
     * spring security在启动时会校验相关配置是否正确
     * 如果不需要校验，返回null即可
     * @return
     */
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    /**
     * 判断返回类对象是否支持校验
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return FilterInvocation.class.isAssignableFrom(aClass);
    }
}
